package com.queclink.ycm.codec;

import com.queclink.ycm.common.utils.DataUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * @author jim.li
 * @email jim.li@queclink.com
 * @date 2022-01-10 09:22:00
 */
public class MessageDecoder extends ByteToMessageDecoder {

    private final int length = 2048;
    private final String START_VALUE = "+";
    private final String HEX_START_VALUE = "2B";
    private final String END_VALUE = "$";
    private final String HEX_END_VALUE = "0D0A";

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out)
            throws Exception {
        if (in.readableBytes() >= length) {
            in.skipBytes(in.readableBytes());
        }
        in.retain();
        byte headArray[] = new byte[in.readableBytes()];
        in.readBytes(headArray);
        String head = new String(headArray);
        in.resetReaderIndex();
        if (DataUtil.isMessyCode(head)) {
            if (DataUtil.bytesToHexString(headArray).startsWith(HEX_START_VALUE)) {
                int strBeginIndex = in.readerIndex();
                int readableBytes = in.readableBytes();
                byte tailArray[] = new byte[2];
                in.getBytes(readableBytes - 2, tailArray);
                in.resetReaderIndex();
                if (!HEX_END_VALUE.equals(DataUtil.bytesToHexString(tailArray))) {
                    in.readerIndex(strBeginIndex);
                    return;
                }
                byte b[] = new byte[in.readableBytes()];
                in.readBytes(b);
                out.add(DataUtil.bytesToHexString(b).getBytes());
            } else {
                ctx.fireChannelRead(out);
            }
        } else if (head.startsWith(START_VALUE)) {
            int strBeginIndex = in.readerIndex();
            int readableBytes = in.readableBytes();
            byte tailArray[] = new byte[1];
            in.getBytes(readableBytes - 1, tailArray);
            String tail = new String(tailArray);
            in.resetReaderIndex();
            if (!END_VALUE.equals(tail)) {
                in.readerIndex(strBeginIndex);
                return;
            }
            byte b[] = new byte[in.readableBytes()];
            in.readBytes(b);
            String msg = new String(b);
            out.add(msg.getBytes());
        } else if (!StringUtils.isEmpty(head)){
            int strBeginIndex = in.readerIndex();
            int readableBytes = in.readableBytes();
            byte tailArray[] = new byte[1];
            in.getBytes(readableBytes - 1, tailArray);
            String tail = new String(tailArray);
            in.resetReaderIndex();
            byte b[] = new byte[in.readableBytes()];
            in.readBytes(b);
            String msg = new String(b);
            out.add(msg.getBytes());
        }else{
            ctx.fireChannelRead(out);
        }
    }
}
